//============================================================================================
/**
 * @file	linear_demo.c
 * @brief	リニアデモ
 * @date	2008.11.25
 * @author	Nozomu Saito
 *
 */
//============================================================================================

#include "common.h"
#include "system/procsys.h"
#include "system/arc_util.h"
#include "system/wipe.h"
#include "application/app_tool.h"
#include "system/snd_tool.h"
#include "linear_demo.naix"

#include "linear_demo.h"

#include "linear_demo_snd_def.h"

#define ANIME_TYPE_NUM	(2)

#define	ANM_ICA	(0)

#define SCENE_NUM	(3)

#define DEMO_DIR_LR	(0)
#define DEMO_DIR_RL	(1)

#define LAST_SCENE_ANM_FRAME	(0xcd * FX32_ONE)


typedef struct DEMO_SCENE_tag
{
	NNSG3dRenderObj			RenderObj;
	NNSG3dResMdl* Model;
	NNSG3dResFileHeader* ResFile;
	void *AnmMem[ANIME_TYPE_NUM];
	NNSG3dAnmObj* AnmObj[ANIME_TYPE_NUM];
}DEMO_SCENE;


typedef struct LINEAR_DEMO_WORK_tag
{
	GF_CAMERA_PTR CameraPtr;//カメラ
	DEMO_SCENE	Scene[SCENE_NUM];
	NNSFndAllocator AnimeAllocator;
	VecFx32 Target;	//注視点
	u8 Dir;
	u8 Sex;
	u8 TimeType;
	u8 EndFlg;
	u8 SceneNo;
	u8 SceneCount;
	u8 dummy[2];
	const int *SeTbl;
}LINEAR_DEMO_WORK;

typedef struct ARC_TBL_tag
{
	int nsbmd;
	u16 anime[ANIME_TYPE_NUM];
}ARC_TBL;

static void InitDisp( void );
static void InitCamera(LINEAR_DEMO_WORK * wk);
static void SetVramBank(void);
static void LoadData(LINEAR_DEMO_WORK *wk);

static BOOL CheckAnm( DEMO_SCENE	*scene, const u8 inSceneNo );
static void StartWipeOut(const u8 inSceneNo, const int inHeap);

#ifdef PM_DEBUG
static BOOL camera_debug(LINEAR_DEMO_WORK * wk);
static void DebugPritnfCameraInfo(GF_CAMERA_PTR camera_ptr);
static void DebugCameraInput(GF_CAMERA_PTR camera_ptr);
static int debug_main(LINEAR_DEMO_WORK * wk);
#endif

//SE
static const int SeTblKogane[SCENE_NUM] = {
	SE_LINEAR_ARRIVAL_LR,
	SE_LINEAR_DEPARTURE_LR,
	SE_LINEAR_RUN_LR,
};

static const int SeTblYamabuki[SCENE_NUM] = {
	SE_LINEAR_ARRIVAL_RL,
	SE_LINEAR_DEPARTURE_RL,
	SE_LINEAR_RUN_RL,
};

//カメラ設定
static const GF_CAMERA_PARAM CameraData[2][SCENE_NUM] = {
	{
		{
			0x1b8152,
			{ -0x55e,-0x3520,0 },
			GF_CAMERA_PERSPECTIV,
			0x08c1,
			0	//dummy
		},
		{
			0x29aec1,
			{ -0x23de,0,0 },
			GF_CAMERA_PERSPECTIV,
			0x05c1,
			0	//dummy
		},
		{
			0x299ec1,
			{ -0x1ffe,0,0 },
			GF_CAMERA_PERSPECTIV,
			0x06c1,
			0	//dummy
		},
	},							//コガネ
	{
		{
			0x1b8152,
			{ -0x55e,0x33e0,0 },
			GF_CAMERA_PERSPECTIV,
			0x08c1,
			0	//dummy
		},
		{
			0x29aec1,
			{ -0x23de,0,0 },
			GF_CAMERA_PERSPECTIV,
			0x05c1,
			0	//dummy
		},
		{
			0x299ec1,
			{ -0x1ffe,0,0 },
			GF_CAMERA_PERSPECTIV,
			0x06c1,
			0	//dummy
		},
	},							//ヤマブキ
};

//カメラ設定
static const VecFx32 CameraShift[2][SCENE_NUM] = {
	{
		{ 0x65ca8, 0x3c3aa, -0x80aa2 },
		{ 0x18000, 0x39f71, -0x51bcb },
		{ 0x0,	   0x13885,  -0x1c7cd  },
	},		//コガネ
	{
		{ -0x5aa89, 0x3c3aa, -0x78ff3 },
		{ 0x18000, 0x39f71, -0x51bcb },
		{ 0x0,	   0x13885,  -0x1c7cd  },
	},		//ヤマブキ
};

typedef struct CAM_CLIP_tag
{
	u16 Near;
	u16 Far;
}CAM_CLIP;

//カメラ設定
static const CAM_CLIP CameraClip[2][SCENE_NUM] = {
	{
		{150,1700},
		{150, 900},
		{150, 900},
	},		//コガネ
	{
		{150,1700},
		{150, 900},
		{150, 900},
	},		//ヤマブキ
};


//エッジマーキングテーブル
static const GXRgb gEdgeColor[8] = {
    GX_RGB(0, 0, 0),
    GX_RGB(4, 4, 4),
    GX_RGB(4, 4, 4),
    GX_RGB(4, 4, 4),
    GX_RGB(4, 4, 4),
    GX_RGB(4, 4, 4),
    GX_RGB(4, 4, 4),
    GX_RGB(4, 4, 4)
};

//アーカイブインデックステーブル
///コガネ側
static ARC_TBL ArcTbl_KMM[3] = {			//コガネ　昼　男
	{
		NARC_linear_demo_kld_s01_m_m_nsbmd,
		{
			NARC_linear_demo_kld_s01_m_m_nsbca,
			NARC_linear_demo_kld_s01_m_m_nsbtp
		}
	},
	{
		NARC_linear_demo_kld_s02_m_m_nsbmd,
		{
			NARC_linear_demo_kld_s02_m_m_nsbca,
			NARC_linear_demo_kld_s02_m_m_nsbtp
		}
	},
	{
		NARC_linear_demo_kld_s03_m_nsbmd,
		{
			NARC_linear_demo_kld_s03_m_nsbca,
			NARC_linear_demo_kld_s03_m_nsbtp,
		}
	},
};

static ARC_TBL ArcTbl_KEM[3] = {			//コガネ　夜　男
	{
		NARC_linear_demo_kld_s01_e_m_nsbmd,
		{
			NARC_linear_demo_kld_s01_e_m_nsbca,
			NARC_linear_demo_kld_s01_e_m_nsbtp
		}
	},
	{
		NARC_linear_demo_kld_s02_e_m_nsbmd,
		{
			NARC_linear_demo_kld_s02_e_m_nsbca,
			NARC_linear_demo_kld_s02_e_m_nsbtp
		}
	},
	{
		NARC_linear_demo_kld_s03_e_nsbmd,
		{
			NARC_linear_demo_kld_s03_e_nsbca,
			NARC_linear_demo_kld_s03_e_nsbtp,
		}
	},
};

static ARC_TBL ArcTbl_KMW[3] = {			//コガネ　昼　女
	{
		NARC_linear_demo_kld_s01_m_w_nsbmd,
		{
			NARC_linear_demo_kld_s01_m_w_nsbca,
			NARC_linear_demo_kld_s01_m_w_nsbtp
		}
	},
	{
		NARC_linear_demo_kld_s02_m_w_nsbmd,
		{
			NARC_linear_demo_kld_s02_m_w_nsbca,
			NARC_linear_demo_kld_s02_m_w_nsbtp
		}
	},
	{
		NARC_linear_demo_kld_s03_m_nsbmd,
		{
			NARC_linear_demo_kld_s03_m_nsbca,
			NARC_linear_demo_kld_s03_m_nsbtp,
		}
	},
};

static ARC_TBL ArcTbl_KEW[3] = {			//コガネ　夜　女
	{
		NARC_linear_demo_kld_s01_e_w_nsbmd,
		{
			NARC_linear_demo_kld_s01_e_w_nsbca,
			NARC_linear_demo_kld_s01_e_w_nsbtp
		}
	},
	{
		NARC_linear_demo_kld_s02_e_w_nsbmd,
		{
			NARC_linear_demo_kld_s02_e_w_nsbca,
			NARC_linear_demo_kld_s02_e_w_nsbtp
		}
	},
	{
		NARC_linear_demo_kld_s03_e_nsbmd,
		{
			NARC_linear_demo_kld_s03_e_nsbca,
			NARC_linear_demo_kld_s03_e_nsbtp,
		}
	},
};

///////////////////////////////
///ヤマブキ側
static ARC_TBL ArcTbl_YMM[3] = {			//ヤマブキ　昼　男
	{
		NARC_linear_demo_yld_s01_m_m_nsbmd,
		{
			NARC_linear_demo_yld_s01_m_m_nsbca,
			NARC_linear_demo_yld_s01_m_m_nsbtp
		}
	},
	{
		NARC_linear_demo_yld_s02_m_m_nsbmd,
		{
			NARC_linear_demo_yld_s02_m_m_nsbca,
			NARC_linear_demo_yld_s02_m_m_nsbtp
		}
	},
	{
		NARC_linear_demo_yld_s03_m_nsbmd,
		{
			NARC_linear_demo_yld_s03_m_nsbca,
			NARC_linear_demo_yld_s03_m_nsbtp,
		}
	},
};

static ARC_TBL ArcTbl_YEM[3] = {			//ヤマブキ　夜　男
	{
		NARC_linear_demo_yld_s01_e_m_nsbmd,
		{
			NARC_linear_demo_yld_s01_e_m_nsbca,
			NARC_linear_demo_yld_s01_e_m_nsbtp
		}
	},
	{
		NARC_linear_demo_yld_s02_e_m_nsbmd,
		{
			NARC_linear_demo_yld_s02_e_m_nsbca,
			NARC_linear_demo_yld_s02_e_m_nsbtp
		}
	},
	{
		NARC_linear_demo_yld_s03_e_nsbmd,
		{
			NARC_linear_demo_yld_s03_e_nsbca,
			NARC_linear_demo_yld_s03_e_nsbtp,
		}
	},
};

static ARC_TBL ArcTbl_YMW[3] = {			//ヤマブキ　昼　女
	{
		NARC_linear_demo_yld_s01_m_w_nsbmd,
		{
			NARC_linear_demo_yld_s01_m_w_nsbca,
			NARC_linear_demo_yld_s01_m_w_nsbtp
		}
	},
	{
		NARC_linear_demo_yld_s02_m_w_nsbmd,
		{
			NARC_linear_demo_yld_s02_m_w_nsbca,
			NARC_linear_demo_yld_s02_m_w_nsbtp
		}
	},
	{
		NARC_linear_demo_yld_s03_m_nsbmd,
		{
			NARC_linear_demo_yld_s03_m_nsbca,
			NARC_linear_demo_yld_s03_m_nsbtp,
		}
	},
};

static ARC_TBL ArcTbl_YEW[3] = {			//ヤマブキ　夜　女
	{
		NARC_linear_demo_yld_s01_e_w_nsbmd,
		{
			NARC_linear_demo_yld_s01_e_w_nsbca,
			NARC_linear_demo_yld_s01_e_w_nsbtp
		}
	},
	{
		NARC_linear_demo_yld_s02_e_w_nsbmd,
		{
			NARC_linear_demo_yld_s02_e_w_nsbca,
			NARC_linear_demo_yld_s02_e_w_nsbtp
		}
	},
	{
		NARC_linear_demo_yld_s03_e_nsbmd,
		{
			NARC_linear_demo_yld_s03_e_nsbca,
			NARC_linear_demo_yld_s03_e_nsbtp,
		}
	},
};

//--------------------------------------------------------------------------------------------
/**
 * プロセス関数：初期化
 *
 * @param	proc	プロセスデータ
 * @param	seq		シーケンス
 *
 * @return	処理状況
 */
//--------------------------------------------------------------------------------------------
PROC_RESULT LinearDemoProc_Init( PROC * proc, int * seq )
{
	u8 i;
	LINEAR_DEMO_WORK *wk;
	LINEAR_DEMO_DAT *dat;

	sys_CreateHeap( HEAPID_BASE_APP, HEAPID_LINEAR_DEMO, 0x31000 );
	wk = PROC_AllocWork( proc, sizeof(LINEAR_DEMO_WORK), HEAPID_LINEAR_DEMO );
	memset( wk, 0, sizeof(LINEAR_DEMO_WORK) );
	dat = PROC_GetParentWork( proc );

	//進行方向を取得
	wk->Dir = dat->Dir;
	//性別取得
	wk->Sex = dat->Sex;
	//時間帯取得
	wk->TimeType = dat->TimeType;

	wk->EndFlg = FALSE;
	//カメラ作成
	wk->CameraPtr = GFC_AllocCamera(HEAPID_LINEAR_DEMO);
	InitDisp();

	//データロード
	LoadData(wk);

	//カメラセット
	InitCamera(wk);

	for(i=0;i<4;i++){
		//ライトセット
		NNS_G3dGlbLightVector(i,
							dat->LightDataPtr->lightVec[i].x,
							dat->LightDataPtr->lightVec[i].y,
							dat->LightDataPtr->lightVec[i].z);
		NNS_G3dGlbLightColor(i, dat->LightDataPtr->Color[i]);
	}

	//グローバルステート書き換え
	NNS_G3dGlbMaterialColorDiffAmb(
				dat->LightDataPtr->Diff,
				dat->LightDataPtr->Amb,
				dat->LightDataPtr->IsSetVtxColor);

	NNS_G3dGlbMaterialColorSpecEmi(
				dat->LightDataPtr->Spec,
				dat->LightDataPtr->Emi,
				dat->LightDataPtr->IsShininess);

	// ポリゴンアトリビュート
	NNS_G3dGlbPolygonAttr(
				dat->LightDataPtr->LightFlag,
				dat->LightDataPtr->polyMode,
				dat->LightDataPtr->cullMode,
				dat->LightDataPtr->polygonID,
				dat->LightDataPtr->alpha,
				dat->LightDataPtr->misc);

	WIPE_SYS_Start(
			WIPE_PATTERN_M, WIPE_TYPE_FADEIN,
			WIPE_TYPE_FADEIN, WIPE_FADE_BLACK, WIPE_DEF_DIV, WIPE_DEF_SYNC, HEAPID_LINEAR_DEMO );

	return PROC_RES_FINISH;
}

//--------------------------------------------------------------------------------------------
/**
 * プロセス関数：メイン
 *
 * @param	proc	プロセスデータ
 * @param	seq		シーケンス
 *
 * @return	処理状況
 */
//--------------------------------------------------------------------------------------------
PROC_RESULT LinearDemoProc_Main( PROC * proc, int * seq )
{
	int rc;
	u8 i;
	BOOL end_flg;
	DEMO_SCENE	*scene;

	LINEAR_DEMO_WORK * wk = PROC_GetWork( proc );

	rc = PROC_RES_CONTINUE;

	scene = &wk->Scene[ wk->SceneNo ];

#if 0
#ifdef PM_DEBUG
	if ( !camera_debug(wk) ){
		rc = debug_main(wk);
	}
#endif
#else
#ifdef PM_DEBUG
	camera_debug(wk);
#endif

	switch(*seq){
	case 0:
		//icaアニメ終了を検出
		if ( CheckAnm( scene, wk->SceneNo ) ){
			//ワイプアウトリクエスト
			StartWipeOut( wk->SceneNo, HEAPID_LINEAR_DEMO );
			(*seq)++;
		}
		break;
	case 1:
		//ワイプアウト待ち
		if (WIPE_SYS_EndCheck() ){
			//シーン変更
			wk->SceneNo++;
			wk->SceneCount++;
			if (wk->SceneCount >= SCENE_NUM){
				rc = PROC_RES_FINISH;
			}else{
				//カメラセット
				InitCamera(wk);
				//ブラックインリクエスト
				APP_WipeStart( APP_WIPE_IN, HEAPID_LINEAR_DEMO );
				(*seq) = 0;
			}
		}
	}

	//SE
	if (scene->AnmObj[ANM_ICA]->frame == 0){
		Snd_SePlay( wk->SeTbl[wk->SceneNo] );
		if (wk->SceneNo == SCENE_NUM-1){
			Snd_DataSetByScene( SND_SCENE_SUB_LINEAR, SEQ_GS_E_LINEAR, 1 );	//曲再生
		}
	}

	for (i=0;i<ANIME_TYPE_NUM;i++){
		if (scene->AnmObj[i]->frame+FX32_ONE < NNS_G3dAnmObjGetNumFrame(scene->AnmObj[i])){
			//アニメフレーム更新
			scene->AnmObj[i]->frame += (FX32_ONE);
		}
	}
#endif

	//描画
	{
		MtxFx33 rotate_tmp = {FX32_ONE,0,0,0,FX32_ONE,0,0,0,FX32_ONE};
		VecFx32 scale = {FX32_ONE,FX32_ONE,FX32_ONE};
		VecFx32 trans = {0,0,0};
		GF_G3X_Reset();
		GFC_CameraLookAt();
		simple_3DModelDraw(	&scene->RenderObj,
							&trans,
							&rotate_tmp,
							&scale);
		GF_G3_RequestSwapBuffers(GX_SORTMODE_MANUAL,GX_BUFFERMODE_W);
	}

	return rc;

}

//--------------------------------------------------------------------------------------------
/**
 * プロセス関数：終了
 *
 * @param	proc	プロセスデータ
 * @param	seq		シーケンス
 *
 * @return	処理状況
 */
//--------------------------------------------------------------------------------------------
PROC_RESULT LinearDemoProc_End( PROC * proc, int * seq )
{
	u8 i,s;
	LINEAR_DEMO_WORK * wk = PROC_GetWork( proc );
	//アニメ解放
	for (s=0;s<SCENE_NUM;s++){
		DEMO_SCENE *scene;
		scene = &wk->Scene[s];
		for(i=0;i<ANIME_TYPE_NUM;i++){
			NNS_G3dFreeAnmObj(	&wk->AnimeAllocator, scene->AnmObj[i]);
			sys_FreeMemoryEz(scene->AnmMem[i]);
		}

		//モデリングデータ解放
		sys_FreeMemoryEz(scene->ResFile);
	}

	//カメラ解放
	GFC_FreeCamera(wk->CameraPtr);
	//ワーク解放
	PROC_FreeWork( proc );
	//3Ｄ関連終了
	simple_3DBGExit();

	//ヒープ解放
	sys_DeleteHeap( HEAPID_LINEAR_DEMO );
	return PROC_RES_FINISH;
}

//----------------------------------------------------------------------------
/**
 * 画面初期化
 *
 * @return	none
 *
 */
//-----------------------------------------------------------------------------
static void InitDisp( void )
{
	sys_VBlankFuncChange( NULL, NULL );	// VBlankセット
	sys_HBlankIntrStop();				// HBlank停止

	GF_Disp_GX_VisibleControlInit();
	GF_Disp_GXS_VisibleControlInit();
	GX_SetVisiblePlane( 0 );
	GXS_SetVisiblePlane( 0 );

	SetVramBank();				// VRAM設定
	simple_3DBGInit(HEAPID_LINEAR_DEMO);
	G3X_EdgeMarking( TRUE );
	//エッジマーキングテーブルセット
	G3X_SetEdgeColorTable(gEdgeColor);
	GF_Disp_DispSelect();	//3Ｄ面設定（上にするか、下にするか）
}

//----------------------------------------------------------------------------
/**
 * カメラ初期化
 *
 * @param	wk		ワークポインタ
 * @return	none
 *
 */
//-----------------------------------------------------------------------------
static void InitCamera(LINEAR_DEMO_WORK * wk)
{
	u8 s_no;
	fx32 near, far;
	VecFx32 target = {0,0,0};
	wk->Target = target;

	s_no = wk->SceneNo;
	//カメラセット
	GFC_InitCameraTDA( &wk->Target,
			CameraData[wk->Dir][s_no].Distance,	// 距離
			&CameraData[wk->Dir][s_no].Angle,	//
			CameraData[wk->Dir][s_no].PerspWay,	// 投射影の角度
			CameraData[wk->Dir][s_no].View,
			TRUE,
			wk->CameraPtr
			);
	GFC_ShiftCamera(&CameraShift[wk->Dir][s_no], wk->CameraPtr);
	near = CameraClip[wk->Dir][s_no].Near*FX32_ONE;
	far = CameraClip[wk->Dir][s_no].Far*FX32_ONE;
	GFC_SetCameraClip(near, far, wk->CameraPtr);

	GFC_AttachCamera(wk->CameraPtr);
}

//===========================================================================
/**
 *
 * ＶＲＡＭバンク設定
 *
 */
//===========================================================================
static void SetVramBank(void)
{
	GF_BGL_DISPVRAM vramSetTable = {
		GX_VRAM_BG_128_C,				// メイン2DエンジンのBG
		GX_VRAM_BGEXTPLTT_NONE,			// メイン2DエンジンのBG拡張パレット
		GX_VRAM_SUB_BG_32_H,			// サブ2DエンジンのBG
		GX_VRAM_SUB_BGEXTPLTT_NONE,		// サブ2DエンジンのBG拡張パレット
		GX_VRAM_OBJ_16_F,				// メイン2DエンジンのOBJ
		GX_VRAM_OBJEXTPLTT_NONE,		// メイン2DエンジンのOBJ拡張パレット
		GX_VRAM_SUB_OBJ_16_I,			// サブ2DエンジンのOBJ
		GX_VRAM_SUB_OBJEXTPLTT_NONE,	// サブ2DエンジンのOBJ拡張パレット
		GX_VRAM_TEX_01_AB,				// テクスチャイメージスロット
		GX_VRAM_TEXPLTT_0123_E			// テクスチャパレットスロット
	};
	GF_Disp_SetBank( &vramSetTable );
}

//----------------------------------------------------------------------------
/**
 * @brief	デモデータロード
 *
 * @param	wk		デモワーク
 *
 * @return	none
 *
 */
//-----------------------------------------------------------------------------
static void LoadData(LINEAR_DEMO_WORK *wk)
{
	u8 i,s;

	ARC_TBL *arc_tbl;

	NNSG3dResTex *texture;
	void *pAnmRes;
	ARCHANDLE* handle;
	//アーカイブハンドルオープン
	handle = ArchiveDataHandleOpen( ARC_LINEAR_DEMO, HEAPID_LINEAR_DEMO );
	//アニメアロケータ
	sys_InitAllocator(&wk->AnimeAllocator,HEAPID_LINEAR_DEMO, 4);

	//読み込むアニメを分岐
	if(wk->Dir == DEMO_DIR_LR){		//コガネ
		//時間帯
		if (wk->TimeType == LINEAR_DEMO_TIME_DAY){
			//性別
			if(wk->Sex == PM_MALE){
				arc_tbl = ArcTbl_KMM;
			}else{
				arc_tbl = ArcTbl_KMW;
			}
		}else{
			//性別
			if(wk->Sex == PM_MALE){
				arc_tbl = ArcTbl_KEM;
			}else{
				arc_tbl = ArcTbl_KEW;
			}
		}
		wk->SeTbl = SeTblKogane;
	}else{							//ヤマブキ
		//時間帯
		if (wk->TimeType == LINEAR_DEMO_TIME_DAY){
			//性別
			if(wk->Sex == PM_MALE){
				arc_tbl = ArcTbl_YMM;
			}else{
				arc_tbl = ArcTbl_YMW;
			}
		}else{
			//性別
			if(wk->Sex == PM_MALE){
				arc_tbl = ArcTbl_YEM;
			}else{
				arc_tbl = ArcTbl_YEW;
			}
		}
		wk->SeTbl = SeTblYamabuki;
	}

	for (s=0;s<SCENE_NUM;s++){
		DEMO_SCENE *scene;
		scene = &wk->Scene[s];
		//モデリングデータをロード
		scene->ResFile = ArchiveDataLoadAllocByHandle( handle, arc_tbl[s].nsbmd, HEAPID_LINEAR_DEMO );
		simple_3DModelSetResFileAlready( &scene->RenderObj, &scene->Model, &scene->ResFile );
		texture = NNS_G3dGetTex(wk->Scene[s].ResFile);	// テクスチャリソース取得

		if (s == SCENE_NUM-1){
			//モデリングデータはグローバルステートを使用する
			NNS_G3dMdlUseGlbDiff(scene->Model);			// ディフューズ
			NNS_G3dMdlUseGlbAmb(scene->Model);				// アンビエント
			NNS_G3dMdlUseGlbSpec(scene->Model);			// スペキュラー
			NNS_G3dMdlUseGlbEmi(scene->Model);				// エミッション
		}
		for(i=0;i<ANIME_TYPE_NUM;i++){
			//アニメーションをロード
			scene->AnmMem[i] = ArchiveDataLoadAllocByHandle( handle, arc_tbl[s].anime[i], HEAPID_LINEAR_DEMO );
			pAnmRes = NNS_G3dGetAnmByIdx(scene->AnmMem[i], 0);
			// 必要量のメモリをアロケートする。
			scene->AnmObj[i] = NNS_G3dAllocAnmObj( &wk->AnimeAllocator, // 使用するアロケータを指定
					                   		       pAnmRes,    // アニメーションリソースを指定
							                       scene->Model);    // モデルリソースを指定

			//イニシャライズ
			NNS_G3dAnmObjInit(scene->AnmObj[i], // アニメーションオブジェクトへのポインタ
			                  pAnmRes, 			// アニメリソースへのポインタ
				              scene->Model,  	// NNSG3dResMdlへのポインタ
					          texture );  		// NNSG3dResTexへのポインタ
			//アニメバインド
			NNS_G3dRenderObjAddAnmObj( &scene->RenderObj, scene->AnmObj[i] );
		}
	}
	//ハンドルクローズ
	ArchiveDataHandleClose( handle );
}

//----------------------------------------------------------------------------
/**
 * @brief	アニメ監視
 *
 * @param	scene		シーンポインタ
 * @param	inSceneNo		シーンナンバー
 *
 * @return	BOOL 		TRUEでアニメ終了
 *
 */
//-----------------------------------------------------------------------------
static BOOL CheckAnm( DEMO_SCENE	*scene, const u8 inSceneNo )
{
	if (inSceneNo+1 >= SCENE_NUM){		//最終シーンか？
		if (scene->AnmObj[ANM_ICA]->frame+FX32_ONE == LAST_SCENE_ANM_FRAME){
			return TRUE;
		}
	}else{
		if (scene->AnmObj[ANM_ICA]->frame+FX32_ONE == NNS_G3dAnmObjGetNumFrame(scene->AnmObj[ANM_ICA])){
			return TRUE;
		}
	}

	return FALSE;
}

//----------------------------------------------------------------------------
/**
 * @brief	ワイプアウト開始
 *
 * @param	inSceneNo		シーンナンバー
 * @param	inHeap			ヒープ
 *
 * @return	none
 *
 */
//-----------------------------------------------------------------------------
static void StartWipeOut(const u8 inSceneNo, const int inHeap)
{
	if (inSceneNo+1 >= SCENE_NUM){		//最終シーンか？
		WIPE_SYS_Start(
			WIPE_PATTERN_WMS, WIPE_TYPE_FADEOUT,
			WIPE_TYPE_FADEOUT, WIPE_FADE_BLACK, WIPE_DEF_DIV, WIPE_DEF_SYNC, inHeap );
	}else{
		WIPE_SYS_Start(
			WIPE_PATTERN_WMS, WIPE_TYPE_SPLITOUT_VSIDE,
			WIPE_TYPE_FADEOUT, WIPE_FADE_BLACK, WIPE_DEF_DIV, WIPE_DEF_SYNC, inHeap );
	}
}

#ifdef PM_DEBUG
#define ANGLE_MOVE	(32)
static BOOL camera_debug(LINEAR_DEMO_WORK * wk)
{
	BOOL rc = FALSE;
	//デバッグ（カメラ設定）
	if (sys.cont & PAD_BUTTON_L){
		DebugCameraInput(wk->CameraPtr);
		rc = TRUE;
	}else if(sys.trg & PAD_BUTTON_SELECT){
		//カメラ戻す
		InitCamera( wk );
	}else if(sys.trg & PAD_BUTTON_X){
		//カメラ情報表示
		DebugPritnfCameraInfo(wk->CameraPtr);
	}
	return rc;
}

static void DebugPritnfCameraInfo(GF_CAMERA_PTR camera_ptr)
{
	CAMERA_ANGLE angle;
	u16 angle_x;

	angle = GFC_GetCameraAngle(camera_ptr);
	//仰角⇒地面からの傾きに変換
	angle_x = -angle.x;

	OS_Printf("距離：%x\n",GFC_GetCameraDistance(camera_ptr));
	OS_Printf("アングル：%x,%x,%x\n",angle.x,angle.y,angle.z);
	OS_Printf("パース：%x\n",GFC_GetCameraPerspWay(camera_ptr));
	OS_Printf("ニア・ファー：%d_%d\n",
			GFC_GetCameraNear(camera_ptr)/FX32_ONE, GFC_GetCameraFar(camera_ptr)/FX32_ONE);
	{
		//バインドターゲットとの差分
		VecFx32 look_at = GFC_GetLookTarget(camera_ptr);
		const VecFx32 *bind = GFC_GetBindTargetVecPtr(camera_ptr);

		OS_Printf("オフセット：%x,%x,%x\n",
				look_at.x-bind->x, look_at.y-bind->y, look_at.z-bind->z);
	}
}

static void DebugCameraInput(GF_CAMERA_PTR camera_ptr)
{
	u8 view;
	fx32 dist;
	u16 persp_way;

	CAMERA_ANGLE angle = {0,0,0,0};
	VecFx32 move = {0,0,0};

	if (1){
		if (sys.cont & PAD_BUTTON_B){			//カメラ回転（公転）
			if (sys.cont & PAD_KEY_UP){
				angle.x = ANGLE_MOVE;
				GFC_AddCameraAngleRev(&angle,camera_ptr);
			}else if (sys.cont & PAD_KEY_DOWN){
				angle.x = -ANGLE_MOVE;
				GFC_AddCameraAngleRev(&angle,camera_ptr);
			}else if (sys.cont & PAD_KEY_LEFT){
				angle.y = -ANGLE_MOVE;
				GFC_AddCameraAngleRev(&angle,camera_ptr);
			}else if (sys.cont & PAD_KEY_RIGHT){
				angle.y = ANGLE_MOVE;
				GFC_AddCameraAngleRev(&angle,camera_ptr);
			}
		}
		else if (sys.cont & PAD_BUTTON_Y){		//カメラ回転（自転）
			if (sys.cont & PAD_KEY_UP){
				angle.x = ANGLE_MOVE;
				GFC_AddCameraAngleRot(&angle,camera_ptr);
			}else if (sys.cont & PAD_KEY_DOWN){
				angle.x = -ANGLE_MOVE;
				GFC_AddCameraAngleRot(&angle,camera_ptr);
			}else if (sys.cont & PAD_KEY_LEFT){
				angle.y = ANGLE_MOVE;
				GFC_AddCameraAngleRot(&angle,camera_ptr);
			}else if (sys.cont & PAD_KEY_RIGHT){
				angle.y = -ANGLE_MOVE;
				GFC_AddCameraAngleRot(&angle,camera_ptr);
			}
		}
		else if (sys.cont & PAD_BUTTON_A){
			if (sys.cont & PAD_KEY_UP){			//カメラズームアウト
				persp_way = GFC_GetCameraPerspWay(camera_ptr);
				if (persp_way+64<0x4000){
					GFC_AddCameraPerspWay(64,camera_ptr);
				}
			}else if (sys.cont & PAD_KEY_DOWN){	//カメラズームイン
				persp_way = GFC_GetCameraPerspWay(camera_ptr);
				if ((u16)(persp_way-64)>0x0000){
					GFC_AddCameraPerspWay(-64,camera_ptr);
				}
			}else if (sys.cont & PAD_KEY_LEFT){
				GFC_AddCameraPerspWay(64,camera_ptr);
				persp_way = GFC_GetCameraPerspWay(camera_ptr);
				//カメラの中心にある2D画像が、崩れずに表示できる距離を求める
				//つぶれずに表示するためには、1Dot　＝　1Unitで計算すればよい
				//カメラが画面中心を見つめるとき、画面半分のサイズは、96Dot
				//表示させたい、カメラのパースを考え、96Dot　＝　96Unitになる距離にすればよい
				dist = FX_Div( FX_Mul( FX_CosIdx( persp_way ), FX_F32_TO_FX32(96) ),
									 FX_SinIdx( persp_way ));
				GFC_SetCameraDistance(dist,camera_ptr);
			}else if(sys.cont & PAD_KEY_RIGHT){
				GFC_AddCameraPerspWay(-64,camera_ptr);
				persp_way = GFC_GetCameraPerspWay(camera_ptr);
				//カメラの中心にある2D画像が、崩れずに表示できる距離を求める
				//つぶれずに表示するためには、1Dot　＝　1Unitで計算すればよい
				//カメラが画面中心を見つめるとき、画面半分のサイズは、96Dot
				//表示させたい、カメラのパースを考え、96Dot　＝　96Unitになる距離にすればよい
				dist = FX_Div( FX_Mul( FX_CosIdx( persp_way ), FX_F32_TO_FX32(96) ),
									 FX_SinIdx( persp_way ));
				GFC_SetCameraDistance(dist,camera_ptr);
			}
		}
		else if (sys.cont & PAD_BUTTON_X){
			fx32 shift;
			if(sys.cont & PAD_BUTTON_R){
				shift = (FX32_ONE*1)/10;
			}else{
				shift = FX32_ONE;
			}
			if (sys.cont & PAD_KEY_UP){
				move.z -= shift;
				GFC_ShiftCamera(&move,camera_ptr);
			}else if (sys.cont & PAD_KEY_DOWN){
				move.z += shift;
				GFC_ShiftCamera(&move,camera_ptr);
			}else if (sys.cont & PAD_KEY_LEFT){
				move.x -= shift;
				GFC_ShiftCamera(&move,camera_ptr);
			}else if (sys.cont & PAD_KEY_RIGHT){
				move.x += shift;
				GFC_ShiftCamera(&move,camera_ptr);
			}
		}else if (sys.cont & PAD_BUTTON_START){
			fx32 shift;
			if(sys.cont & PAD_BUTTON_R){
				shift = (FX32_ONE*1)/10;
			}else{
				shift = FX32_ONE;
			}
			if (sys.cont & PAD_KEY_UP){
				move.y += shift;
				GFC_ShiftCamera(&move,camera_ptr);
			}else if (sys.cont & PAD_KEY_DOWN){
				move.y -= shift;
				GFC_ShiftCamera(&move,camera_ptr);
			}
		}else if(sys.cont & PAD_BUTTON_R){
			fx32 near,far;
			if (sys.cont & PAD_KEY_UP){
				far = GFC_GetCameraFar(camera_ptr);
				near = GFC_GetCameraNear(camera_ptr);
				far += FX32_ONE;
				OS_Printf("far=%d\n",far/FX32_ONE);
				GFC_SetCameraClip(near,far,camera_ptr);
			}else if (sys.cont & PAD_KEY_DOWN){
				far = GFC_GetCameraFar(camera_ptr);
				near = GFC_GetCameraNear(camera_ptr);
				far -= FX32_ONE;
				OS_Printf("far=%d\n",far/FX32_ONE);
				GFC_SetCameraClip(near,far,camera_ptr);
			}else if(sys.cont & PAD_KEY_RIGHT){
				far = GFC_GetCameraFar(camera_ptr);
				near = GFC_GetCameraNear(camera_ptr);
				near += FX32_ONE;
				OS_Printf("near=%d\n",near/FX32_ONE);
				GFC_SetCameraClip(near,far,camera_ptr);
			}else if(sys.cont & PAD_KEY_LEFT){
				far = GFC_GetCameraFar(camera_ptr);
				near = GFC_GetCameraNear(camera_ptr);
				near -= FX32_ONE;
				OS_Printf("near=%d\n",near/FX32_ONE);
				GFC_SetCameraClip(near,far,camera_ptr);
			}
		}
		else if (sys.cont & PAD_KEY_UP){	//カメラを遠ざける
			GFC_AddCameraDistance(FX32_ONE,camera_ptr);
		}else if (sys.cont & PAD_KEY_DOWN){	//カメラを近づける
			GFC_AddCameraDistance(-FX32_ONE,camera_ptr);
		}
	}
}

static int debug_main(LINEAR_DEMO_WORK * wk)
{
	u8 i;
	DEMO_SCENE	*scene;
	scene = &wk->Scene[ wk->SceneNo ];

	if (sys.trg & PAD_BUTTON_R){
		wk->SceneNo++;
		wk->SceneCount++;
		if (wk->SceneCount >= SCENE_NUM){
			wk->SceneNo = 0;
			wk->SceneCount = 0;
		}
		//カメラセット
		InitCamera(wk);
	}else if(sys.trg & PAD_BUTTON_B){
		return PROC_RES_FINISH;
	}

	//SE
	if (scene->AnmObj[ANM_ICA]->frame == 0){
		Snd_SePlay( wk->SeTbl[wk->SceneNo] );
	}

	for (i=0;i<ANIME_TYPE_NUM;i++){
		//アニメフレーム更新
		scene->AnmObj[i]->frame += (FX32_ONE);
		if (scene->AnmObj[i]->frame >= NNS_G3dAnmObjGetNumFrame(scene->AnmObj[i])){
			scene->AnmObj[i]->frame = 0;
		}
	}

	return PROC_RES_CONTINUE;
}
#endif	//PM_DEBUG